package com.cmc.cloud.cmclink.doc.service.impl.so;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.cmc.cloud.cmclink.common.filter.FilterGroup;
import com.cmc.cloud.cmclink.common.filter.FilterRule;
import com.cmc.cloud.cmclink.common.filter.enums.FilterCondition;
import com.cmc.cloud.cmclink.doc.api.document.emums.ExImTypeEnum;
import com.cmc.cloud.cmclink.doc.entity.VoyageBsaDO;
import com.cmc.cloud.cmclink.doc.entity.VoyageBsaHgDO;
import com.cmc.cloud.cmclink.doc.mapper.SoMapper;
import com.cmc.cloud.cmclink.doc.mapper.VoyageBsaCbaMapper;
import com.cmc.cloud.cmclink.doc.mapper.VoyageBsaHgMapper;
import com.cmc.cloud.cmclink.doc.mapper.VoyageBsaMapper;
import com.cmc.cloud.cmclink.doc.rpcservice.CustomerRpcService;
import com.cmc.cloud.cmclink.doc.vo.sovo.sovo.*;
import com.cmc.cloud.cmclink.doc.vo.voyagebsacbavo.VoyageBsaCbaAllocationSpaceVO;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订舱主 查询 Service 实现类
 *
 * @author 招商轮船-管理员
 */
@Service
@Validated
public class SoQueryServiceImpl {
    @Resource
    private SoMapper soMapper;
    @Resource
    private VoyageBsaMapper voyageBsaMapper;
    @Resource
    private VoyageBsaHgMapper voyageBsaHgMapper;
    @Resource
    private VoyageBsaCbaMapper voyageBsaCbaMapper;
    @Resource
    CustomerRpcService nameTransferService;

    private final Gson gson = new Gson();

    public SoBsaALlCountVO querySoBsaCustomerCount(SoBsaCountReqVO req) {
        SoBsaALlCountVO result = new SoBsaALlCountVO();
        result.setSoBsaCountReq(req);
        LambdaQueryWrapperX<VoyageBsaDO> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.eq(VoyageBsaDO::getPolCodes, req.getPolCode())
                .eq(VoyageBsaDO::getVesselCode, req.getBookingVessel())
                .eq(VoyageBsaDO::getVoyage, req.getBookingVoyage())
                .eq(VoyageBsaDO::getExImType, ExImTypeEnum.EX.getValue());
        VoyageBsaDO voyageBsa = voyageBsaMapper.selectOne(queryWrapperX);
        if (voyageBsa == null) {
            return null;
        }
        // 查询
        Map<String, VoyageBsaHgDO> voyageBsaHgMap = voyageBsaHgMapper.selectList(new LambdaQueryWrapperX<VoyageBsaHgDO>().eq(VoyageBsaHgDO::getVoyageBsaId, voyageBsa.getId())).stream().collect(Collectors.toMap(e -> e.getCntrSize() + e.getCntrType(), e -> e));
        SoBsaCountVO soBsaCount = BeanUtil.copyProperties(voyageBsa, SoBsaCountVO.class);
        result.setSoBsaCount(soBsaCount);
        soBsaCount.setPolCode(req.getPolCode());

        Long receivedUnit = 0L;
        Long waitUnit = 0L;
        BigDecimal receivedTeu = BigDecimal.ZERO;
        BigDecimal waitTeu = BigDecimal.ZERO;
        BigDecimal receivedWgtTons = BigDecimal.ZERO;
        BigDecimal waitWgtTons = BigDecimal.ZERO;

        List<SoBsaSecondCountVO> soBsaSecondCountList = soMapper.querySoBsaSecondCount(req);
        result.setSoBsaSecondCountList(soBsaSecondCountList);
        // 分类计算
        Map<String, Long> cntrSizeTypeReceivedSum = new HashMap<>(16);
        Map<String, Long> cntrSizeTypeWaitSum = new HashMap<>(16);
        if (CollectionUtil.isNotEmpty(soBsaSecondCountList)) {
            for (SoBsaSecondCountVO secondCount : soBsaSecondCountList) {
                String key = secondCount.getCntrSize() + secondCount.getCntrType();
                receivedTeu = receivedTeu.add(secondCount.getReceivedTeu());
                waitTeu = waitTeu.add(secondCount.getWaitTeu());
                receivedUnit += secondCount.getReceivedUnit();
                waitUnit += secondCount.getWaitUnit();
                if (voyageBsaHgMap.get(key) != null) {
                    Long unitReceive = cntrSizeTypeReceivedSum.get(key);
                    if (unitReceive == null) {
                        cntrSizeTypeReceivedSum.put(key, secondCount.getReceivedUnit());
                    } else {
                        cntrSizeTypeReceivedSum.put(key, unitReceive + secondCount.getReceivedUnit());
                    }
                    Long unitWait = cntrSizeTypeWaitSum.get(key);
                    if (unitWait == null) {
                        cntrSizeTypeWaitSum.put(key, secondCount.getWaitUnit());
                    } else {
                        cntrSizeTypeWaitSum.put(key, unitWait + secondCount.getWaitUnit());
                    }
                }
                receivedWgtTons = receivedWgtTons.add(secondCount.getReceivedWgtTons());
                waitWgtTons = waitWgtTons.add(secondCount.getWaitWgtTons());
            }
        }
        soBsaCount.setReceivedTeu(receivedTeu);
        soBsaCount.setWaitTeu(waitTeu);
        // 默认数据相同
        soBsaCount.setReceivedThresholdTeu(receivedTeu);
        soBsaCount.setWaitThresholdTeu(waitTeu);
        soBsaCount.setReceivedWgtTons(receivedWgtTons);
        soBsaCount.setWaitWgtTons(waitWgtTons);
        soBsaCount.setReceivedUnit(receivedUnit);
        soBsaCount.setWaitUnit(waitUnit);
        //计算阈值后的值
        if (CollectionUtil.isNotEmpty(voyageBsaHgMap)) {
            for (Map.Entry<String, VoyageBsaHgDO> voyageBsaHg : voyageBsaHgMap.entrySet()) {
                String key = voyageBsaHg.getKey();
                VoyageBsaHgDO bsaHg = voyageBsaHg.getValue();
                Long unitReceive = cntrSizeTypeReceivedSum.get(key);
                if (unitReceive != null && bsaHg.getUnitThreshold() != null && unitReceive > bsaHg.getUnitThreshold()) {
                    BigDecimal change = bsaHg.getTeuStandard().subtract(new BigDecimal(bsaHg.getCntrSize()).divide(new BigDecimal(20)));
                    BigDecimal changeTeu = new BigDecimal(unitReceive - bsaHg.getUnitThreshold()).multiply(change);
                    soBsaCount.setReceivedThresholdTeu(soBsaCount.getReceivedThresholdTeu().add(changeTeu));
                }
                Long unitWait = cntrSizeTypeWaitSum.get(key);
                if (unitWait != null && bsaHg.getUnitThreshold() != null && unitWait > bsaHg.getUnitThreshold()) {
                    BigDecimal change = bsaHg.getTeuStandard().subtract(new BigDecimal(bsaHg.getCntrSize()).divide(new BigDecimal(20)));
                    BigDecimal changeTeu = new BigDecimal(unitWait - bsaHg.getUnitThreshold()).multiply(change);
                    soBsaCount.setWaitThresholdTeu(soBsaCount.getWaitThresholdTeu().add(changeTeu));
                }
            }
        }

        List<SoBsaCustomerCountVO> soBbsaCustomerCountList = soMapper.querySoBsaCustomerCount(req);
        result.setSoBsaCustomerCountList(soBbsaCustomerCountList);
        // 计算 预留舱位
        List<VoyageBsaCbaAllocationSpaceVO> allocationSpaceList = voyageBsaCbaMapper.queryAllocationSpaceAndBookingParty(voyageBsa.getId());
        Map<String, Integer> allocationMap = new LinkedHashMap<>(16);
        if (CollectionUtil.isNotEmpty(allocationSpaceList)) {
            for (VoyageBsaCbaAllocationSpaceVO space : allocationSpaceList) {
                FilterGroup group = gson.fromJson(space.getJsonString(), FilterGroup.class);
                List<FilterRule> rules = group.getFilterRules();
                if (CollectionUtil.isNotEmpty(rules)) {
                    for (FilterRule rule : rules) {
                        if ("bookingParty".equals(rule.getFieldName())) {
                            String[] values = rule.getValue().split(";");
                            // 多个不判断 ,只取第一个
                            if (FilterCondition.IN.name().equals(rule.getCondition().name()) && values.length == 1) {
                                if (allocationMap.get(values[0]) == null) {
                                    allocationMap.put(values[0], space.getAllocationSpace());
                                }
                            }
                            if (FilterCondition.EQUAL.name().equals(rule.getCondition().name())) {
                                if (allocationMap.get(rule.getValue()) == null) {
                                    allocationMap.put(rule.getValue(), space.getAllocationSpace());
                                }
                            }
                        }
                    }
                }
            }
        }
        if (CollectionUtil.isNotEmpty(soBbsaCustomerCountList)) {
            for (SoBsaCustomerCountVO count : soBbsaCustomerCountList) {
                Integer allocationSpace = allocationMap.get(count.getBookingParty());
                if (allocationSpace != null) {
                    count.setAllocationSpace(allocationSpace);
                }
                allocationMap.remove(count.getBookingParty());
            }
        }
        if (CollectionUtil.isNotEmpty(allocationMap)) {
            for (Map.Entry<String, Integer> other : allocationMap.entrySet()) {
                SoBsaCustomerCountVO temp = new SoBsaCustomerCountVO();
                temp.setPolCode(req.getPolCode());
                temp.setBookingParty(other.getKey());
                temp.setAllocationSpace(other.getValue());
                soBbsaCustomerCountList.add(temp);
            }
        }
        if (CollectionUtil.isNotEmpty(soBbsaCustomerCountList)) {
            List<String> collect = soBbsaCustomerCountList.stream().map(SoBsaCustomerCountVO::getBookingParty).collect(Collectors.toList());
            Map<String, String> companyNameMap = nameTransferService.getCompanyLocalNameMap(collect);
            soBbsaCustomerCountList.forEach(e -> {
                String companyNameEn = companyNameMap.get(e.getBookingParty());
                if (StringUtils.isNotBlank(companyNameEn)) {
                    e.setBookingParty(companyNameEn);
                }
            });
        }
        return result;
    }
}
